/*
 *  CHEEZBURGER.h
 *  TubeTruck
 *
 *  Created by Aeturnum on 6/6/08.
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
 *
 */

#include <vector>
#include <assert.h>
#include <exception>
#include <map>

#include "TubeTruckTypes.h"
#include "serialization.h"
#include "unserialization.h" 
#include "smartalloc_wrap.h"
#include "Packet.h"
#include "Signable.h"
#include "Signiture.h"
#include "Encryptable.h"
#include "RSA.h"
#include "util.h"
#include "AppDataSegment.h"

namespace TTP {
   
   struct lessThan
   {
      bool operator()(int a, int b) const
      {
         return a < b;
      }
   };
   
   class CHEEZBURGER : public Packet, public Crypt::Signable, public Crypt::Encryptable {
   protected:
      std::vector<id_hash> mIdHashList;
      std::vector<ack_num> mAckNumbers;
      std::map<ack_num, AppDataSegment, lessThan> mData;
      int dataIndex;
      std::vector<byte> mBlowfishIv;
      
      void fillEncryptedSection();
   public:
      
      CHEEZBURGER();
      CHEEZBURGER(id_hash);
      CHEEZBURGER(id_hash, std::vector<byte>&, std::vector<uint32_t>&, std::vector<uint32_t>&);
      ~CHEEZBURGER();
      
      //accessors
      std::vector<id_hash> getHashList() const;
      std::vector<ack_num> getAckNumbers() const;
      uint32_t getAckNumber(id_hash) const;
      std::vector< std::vector<byte> > getDataVectors() const;
      std::vector<ack_num> getDataAckNumbers() const;
      std::vector<byte> getDataVector(ack_num) const;
      std::vector<byte> getBlowfishIv();
      
      // modifiers
      void addHashAckPair(id_hash, ack_num);
      void setAckNumber(ack_num);
      void addDataSegment(std::vector<byte>&);
      void addDataSegment(ack_num, std::vector<byte>&);
      void setBlowfishIv(std::vector<byte>&);

      // idhash
      void  setSourceIdHash(id_hash);
      id_hash getSourceIdHash() const;
      
      // inherited
      void fromVec(std::vector<byte>::const_iterator &vit, std::vector<byte>::const_iterator &end);
      void toVec(std::vector<byte> &vec) const;
      
      void setEncryptedData(std::vector<byte>&);
      void setPlainText(std::vector<byte>&);
      std::vector<byte> getEncryptedSection();
      
      std::vector<byte> getUnsignedData() const;
   };
}
